﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Kugar.ERPFramework.View.WinForm
{
    public partial class ControlLayoutCollection : UserControl
    {
        private ControlFieldsManager _manager = null;
        private ControlCollectionLayoutType _layoutType= ControlCollectionLayoutType.GridLayout;
        private Control _parentPanel = null;
        private Control _currentCollection = null;

        protected ControlLayoutCollection()
        {
            InitializeComponent();
        }

        public ControlLayoutCollection(ControlFieldsManager manager,Control parentControl)
        {
            _manager = manager;
            _manager.CollectionChanged += _manager_CollectionChanged;
            _parentPanel = parentControl;
            this.BackColor = parentControl.BackColor;

        }


        /// <summary>
        ///     控件容器的布局方式
        /// </summary>
        [DefaultValue(ControlCollectionLayoutType.FlowLayout)]
        [Browsable(true)]
        public  ControlCollectionLayoutType LayoutType
        {
            get { return _layoutType; }
            set
            {
                if (_layoutType!=value)
                {
                    _layoutType = value;
                    OnLayoutTypeChanged();
                }
            }
        }

        /// <summary>
        ///     重新刷新字段布置
        /// </summary>
        public void RefreshLayout()
        {
            this.Controls.Clear();
            if (LayoutType== ControlCollectionLayoutType.GridLayout)
            {
                Panel panel = null;

                if (!(_currentCollection is Panel))
                {
                    panel = createPanel(_parentPanel.BackColor);
                    panel.Dock = DockStyle.Fill;
                    _parentPanel.Controls.Add(panel);
                }
                else
                {
                    panel = (Panel)_currentCollection;
                    panel.Controls.Clear();
                }
                
                GridControlLayout(panel);

                _currentCollection = panel;
            }
            else
            {
                Panel flowPanel = null;

                if (!(_currentCollection is FlowLayoutPanel))
                {
                    flowPanel = new FlowLayoutPanel();
                    flowPanel.BackColor = _parentPanel.BackColor;
                    flowPanel.Dock = DockStyle.Fill;
                    _parentPanel.Controls.Add(flowPanel);
                }
                else
                {
                    flowPanel = (FlowLayoutPanel)_currentCollection;
                    flowPanel.Controls.Clear();
                }

                FlowControlLayout(flowPanel);

                _currentCollection = flowPanel;
            }
        }

        public void ShowFieldVisibleConfig()
        {
            
        }

        public void ShowFieldLocationDesign()
        {
            
        }

        public event EventHandler LayoutTypeChanged;

        void _manager_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            RefreshLayout();

            //var field = (ControlFieldConfigBase) e.NewItems[0];

            //if (LayoutType == ControlCollectionLayoutType.GridLayout)
            //{
            //    AppendGridField(field);
            //}
            //else
            //{
            //    AppendFlowField(field);
            //}
        }

        protected virtual void OnLayoutTypeChanged()
        {
            RefreshLayout();

            if (LayoutTypeChanged!=null)
            {
                LayoutTypeChanged(this, EventArgs.Empty);
            }
        }

        const int editCtrlDefaultWidth = 80;
        const int editCtrlDefaultHeight = 20;
        const int ctrlSpacing = 5;
        protected virtual void FlowControlLayout(Control parentControl)
        {
            parentControl.Controls.Clear();

            var fields = _manager;

            if (fields == null || fields.Count <= 0)
            {
                return;
            }

            //var currentX = 2;
            //var currentY = 5;

            //const int groupSpacing = 10;

            foreach (var field in fields)
            {
                var ctrlField = (ControlFieldConfigBase)field.Value;

                ctrlField.ApplyToControl();

                AppendFlowField(ctrlField);

                //int labelWidth = 0;
                //int labelHeight = 0;
                //int editWidth = 0;
                //int editHeight = 0;

                //var panel = createPanel(parentControl.BackColor);

                //if (ctrlField.LabelCtrl != null)
                //{
                //    panel.Controls.Add(ctrlField.LabelCtrl);
                //    var labelSize = ctrlField.GetLabelCtrlSize();
                //    ctrlField.LabelCtrl.BackColor = parentControl.BackColor;
                //    labelWidth = labelSize.Width + ctrlField.LabelCtrl.Margin.Right + ctrlSpacing;
                //    labelHeight = labelSize.Height + ctrlField.LabelCtrl.Margin.Bottom + ctrlSpacing;

                //    ctrlField.LabelCtrl.Left = currentX;
                //    ctrlField.LabelCtrl.Top = currentY;

                //    currentX += (labelWidth);
                //}

                

                //if (ctrlField.EditorCtrl != null)
                //{
                //    parentControl.Controls.Add(ctrlField.EditorCtrl);

                //    ctrlField.EditorCtrl.Width = editCtrlDefaultWidth;
                //    ctrlField.EditorCtrl.Height = editCtrlDefaultHeight;

                //    ctrlField.EditorCtrl.Left = currentX;
                //    ctrlField.EditorCtrl.Top = currentY;

                //    editWidth = ctrlField.EditorCtrl.Width + ctrlField.EditorCtrl.Margin.Right + ctrlSpacing;
                //    editHeight = ctrlField.EditorCtrl.Height;
                //    currentX += (editWidth);
                //}

                //if (editHeight==0)
                //{
                //    editHeight = labelHeight;
                //}

                //panel.Width = currentX;
                //panel.Height = editHeight;
                
                //parentControl.Controls.Add(panel);

                //if (currentX + labelWidth + editWidth > parentControl.ClientSize.Width)
                //{
                //    currentY += editCtrlDefaultHeight;
                //}

                //if (ctrlField.LabelCtrl != null)
                //{
                //    ctrlField.LabelCtrl.Left = currentX;
                //    ctrlField.LabelCtrl.Top = currentY;
                //}

                

                //if (ctrlField.EditorCtrl != null)
                //{

                //}

                //currentX += editWidth;

                Center(ctrlField.EditorCtrl, ctrlField.LabelCtrl);

                //currentX += groupSpacing;
            }
        }

        protected virtual void GridControlLayout(Control parentControl)
        {
            parentControl.Controls.Clear();

            var fields = _manager;

            if (fields == null || fields.Count <= 0)
            {
                return;
            }

            var currentX = 2;
            var currentY = 5;
            const int editCtrlDefaultWidth = 80;
            const int editCtrlDefaultHeight = 20;
            const int ctrlSpacing = 5;
            const int groupSpacing = 10;



            foreach (var field in fields)
            {
                var ctrlField = (ControlFieldConfigBase)field.Value;

                ctrlField.ApplyToControl();


                int labelWidth = 0;
                int labelHeight = 0;

                int editWidth = 0;
                int editHeight = 0;

                if (ctrlField.LabelCtrl != null)
                {
                    parentControl.Controls.Add(ctrlField.LabelCtrl);
                    var labelSize = ctrlField.GetLabelCtrlSize();
                    ctrlField.LabelCtrl.BackColor = parentControl.BackColor;
                    labelWidth = labelSize.Width + ctrlField.LabelCtrl.Margin.Right + ctrlSpacing;
                    labelHeight = labelSize.Height + ctrlField.LabelCtrl.Margin.Bottom + ctrlSpacing;

                }

                if (ctrlField.EditorCtrl != null)
                {
                    parentControl.Controls.Add(ctrlField.EditorCtrl);

                    ctrlField.EditorCtrl.Width = editCtrlDefaultWidth;
                    ctrlField.EditorCtrl.Height = editCtrlDefaultHeight;

                    editWidth = ctrlField.EditorCtrl.Width + ctrlField.EditorCtrl.Margin.Right + ctrlSpacing;
                    editHeight = ctrlField.EditorCtrl.Height;
                }


                if (currentX + labelWidth + editWidth > parentControl.ClientSize.Width)
                {
                    currentY += editCtrlDefaultHeight;
                }

                if (ctrlField.LabelCtrl != null)
                {
                    ctrlField.LabelCtrl.Left = currentX;
                    ctrlField.LabelCtrl.Top = currentY;
                }

                currentX += (labelWidth);

                if (ctrlField.EditorCtrl != null)
                {
                    ctrlField.EditorCtrl.Left = currentX;
                    ctrlField.EditorCtrl.Top = currentY;
                }

                currentX += editWidth;

                Center(ctrlField.EditorCtrl, ctrlField.LabelCtrl);

                currentX += groupSpacing;
            }
        }

        protected virtual void AppendGridField(ControlFieldConfigBase field)
        {
            
        }

        protected virtual void AppendFlowField(ControlFieldConfigBase ctrlField)
        {
            var panel = createPanel(_currentCollection.BackColor);

            var currentX = 2;
            var currentY = 5;

            int labelWidth = 0;
            int labelHeight = 0;
            int editWidth = 0;
            int editHeight = 0;

            if (ctrlField.LabelCtrl != null)
            {
                panel.Controls.Add(ctrlField.LabelCtrl);
                var labelSize = ctrlField.GetLabelCtrlSize();
                ctrlField.LabelCtrl.BackColor = _currentCollection.BackColor;
                labelWidth = labelSize.Width + ctrlField.LabelCtrl.Margin.Right + ctrlSpacing;
                labelHeight = labelSize.Height + ctrlField.LabelCtrl.Margin.Bottom + ctrlSpacing;

                ctrlField.LabelCtrl.Left = currentX;
                ctrlField.LabelCtrl.Top = currentY;

                currentX += (labelWidth);
            }



            if (ctrlField.EditorCtrl != null)
            {
                panel.Controls.Add(ctrlField.EditorCtrl);

                ctrlField.EditorCtrl.Width = editCtrlDefaultWidth;
                ctrlField.EditorCtrl.Height = editCtrlDefaultHeight;

                ctrlField.EditorCtrl.Left = currentX;
                ctrlField.EditorCtrl.Top = currentY;

                editWidth = ctrlField.EditorCtrl.Width + ctrlField.EditorCtrl.Margin.Right + ctrlSpacing;
                editHeight = ctrlField.EditorCtrl.Height;
                currentX += (editWidth);
            }

            if (editHeight == 0)
            {
                editHeight = labelHeight;
            }

            panel.Width = currentX;
            panel.Height = editHeight;

            Center(ctrlField.EditorCtrl, ctrlField.LabelCtrl);

            _currentCollection.Controls.Add(panel);
        }

        private void Center(Control baseCtrl, params Control[] targetCtrl)
        {
            var baseHeight = baseCtrl.Height;

            var graphics = Graphics.FromHwnd(baseCtrl.Handle);

            var baseRange = graphics.VisibleClipBounds;

            var baseLineY = (int)baseRange.Height / 2 + baseCtrl.Top;

            graphics.Dispose();

            foreach (var control in targetCtrl)
            {
                var g = Graphics.FromHwnd(control.Handle);

                var r = g.VisibleClipBounds;

                g.Dispose();

                control.Top = control.Top + (baseLineY - ((int)r.Height / 2 + control.Top));
            }
        }

        private Panel createPanel(Color backColor)
        {
            return new Panel() { BackColor = backColor };
        }
    }

    public enum ControlCollectionLayoutType
    {
        /// <summary>
        /// 网格布局,该布局不随窗体变化而自动调整,只有在调用刷新布局时才重新排列,也可自由调整控件位置
        /// </summary>
        GridLayout,

        /// <summary>
        /// 流布局,所有控件从左到右依次排列,并随窗体大小而自动调整
        /// </summary>
        FlowLayout
    }
}
